package com.zsc.wxapp.services.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zsc.wxapp.entity.*;
import com.zsc.wxapp.services.UploadImageService;
import com.zsc.wxapp.utils.ImageUtil;
import com.zsc.wxapp.utils.MinIOUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;


@Service
@Slf4j
public class UploadImageServiceImpl implements UploadImageService {

    @Value("${api.local.url}")
    private String apiLocalUrl;

    @Value("${api.local.python}")
    private String pythonUrl;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private MinIOUtil minIOUtil;

    /**
     * 向品规接口发送请求，处理返回的json数据
     *
     * @param file 图片文件
     * @return String 字符串
     */
    @Override
    public String uploadToExternalAPI(MultipartFile file) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        headers.set("apikey", "oE2PzTohoiDMwbUIZuJXyGK2Shzd1de");

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("file_list", file.getResource());
        body.add("model_name", "custom");
        body.add("download_image", "false");

        // 发送请求
        log.info("向甲方接口发送post请求");
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);

        // 接收返回的json数据
        ResponseEntity<String> response = restTemplate.exchange(apiLocalUrl, HttpMethod.POST, requestEntity, String.class);
        String responseBody = response.getBody();
//        log.info("处理之前的数据是：" + responseBody);

//        String result = processedData(responseBody);
//        log.info("处理完的json数据是：{}:", result);

        // json数据写入到文件中
//        writeIntoJSON(responseBody);

//        return result;
        return responseBody;
    }

    /**
     * 向python发送请求
     *
     * @param file
     * @param json
     * @param url
     * @param downloadImage
     * @return
     * @throws Exception
     */
    @Override
    public PythonResponse uploadToPython(MultipartFile file, String json, String url, String downloadImage) throws Exception {
        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("data", json);  // JSON 字符串作为普通字符串
        body.add("url", url); // 图片url
        body.add("image", null);  // 文件对象
        body.add("download_image", downloadImage); // 是否传输base64位图片数据
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        //给python端发送请求
        HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(pythonUrl, requestEntity, String.class);
        String jsonResponse = response.getBody();
//        log.info("python端返回的数据是：{}", jsonResponse);

        // 将 JSON 字符串转换为 PythonResponse 对象
        PythonResponse responseData = new ObjectMapper().readValue(response.getBody(), PythonResponse.class);

        //判断返回的状态码是多少
        if (responseData.getCode().equals("200")) {
            log.info("python端返回的数据是：{}", responseData);
            return responseData;
        } else if (responseData.getCode().equals("800")) {
            log.info("python端返回的数据是：{}", responseData);
            throw new Exception("未识别出烟盒和价签");
//            throw new Exception("800");
        } else if (responseData.getCode().equals("801")) {
            log.info("python端返回的数据是：{}", responseData);
            throw new Exception("价签分辨率过低");
//            throw new Exception("801");
        } else if (responseData.getCode().equals("802")) {
            log.info("python端返回的数据是：{}", responseData);
            log.info("图像方向有误，旋转图片后再次发送");
            // 旋转图片后再向python端发送一次请求
            try {
                // 旋转图片
//                file = ImageUtil.rotateImage(file);
//                String newUrl = minIOUtil.uploadFile(file);
//                return PythonResponse.builder()
//                        .markedImage(newUrl)
//                        .build();

                // 再次发送数据
//                body.remove("url");
//                body.add("url", newUrl);
//                requestEntity = new HttpEntity<>(body, headers);
//                response = restTemplate.postForEntity(pythonUrl, requestEntity, String.class);
//
//                log.info("第二次发送识别请求");
//                responseData = new ObjectMapper().readValue(response.getBody(), PythonResponse.class);
//                if (responseData.getCode().equals("200")) {
//                    return responseData;
//                } else {
//                    throw new Exception("未识别出价签");
//                }
                throw new Exception("图片方向错误");
            } catch (IOException e) {
                log.info("图片旋转失败");
                throw new Exception("图片旋转失败");
            }

        } else {
            throw new Exception("未知错误");
        }
    }


    /**
     * 处理品规识别返回的json数据
     *
     * @param responseBody
     * @return
     */
    public String processedData(String responseBody) {
        // 去除json数据中的\符号
        responseBody = responseBody.replace("\\", "");

        //去掉两边的 ""[" 和 "]""
        responseBody = responseBody.substring(2, responseBody.length() - 2);

        Detect detect;

        // 把json数据装成java中的类对象
        try {
            ObjectMapper objectMapper = new ObjectMapper();

            detect = objectMapper.readValue(responseBody, Detect.class);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("反序列化失败");
        }

        List<Box> boxes = detect.getBox();
        List<PinguiDetail> pinguiDetail;
        pinguiDetail = detect.getInfo().getPinguiDetails();

        // 去除pinguiDetail中，count为1的数据
        pinguiDetail.removeIf(item -> item.getCount() == 1);
        pinguiDetail.removeIf(item -> item.getItem_id().equals("tag"));

        // 去除box中重复的数据
        for (PinguiDetail detail : pinguiDetail) {
            Box copy = boxes.stream()
                    .filter(box -> box.getItem_id().equals(detail.getItem_id()))
                    .findFirst()
                    .orElse(null);

            boxes.removeIf(box -> box.getItem_id().equals(detail.getItem_id()));
            // 把备份的box数据重新插回到集合中，只保留一个
            if (copy != null) {
                // 如果copy不为空就插入集合中
                boxes.add(copy);
            }
        }

        // 把detect数据装成json数据
        detect.setBox(boxes);
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            String json = objectMapper.writeValueAsString(detect);
            json = json.replace("\"", "\\\"");

            // json数据写入到文件中
            writeIntoJSON(json);

            String result = "\"[" + json + "]\"";
            return result;
        } catch (Exception e) {
            throw new RuntimeException("序列化失败");
        }
    }

    /**
     * 把处理后的json数据写入文件中
     * 测试用
     *
     * @param json
     */
    private void writeIntoJSON(String json) {
        json = json.replace("\\", "");
        json = json.substring(2, json.length() - 2);
        String fillPath = "D:/superEngineering/Java/vue/jlt-test/test.json";

        try {
            FileWriter writer = new FileWriter(fillPath);
            writer.write(json);
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("写入文件失败");
        }
    }

}
